package com.apache.info.service.impl;

import com.apache.api.manager.PluginConnector;
import com.apache.api.vo.ParamsVo;
import com.apache.cache.service.CacheManager;
import com.apache.cache.service.impl.LoadCacheFactory;
import com.apache.cache.util.Validator;
import com.apache.database.db.IDao;
import com.apache.database.model.MethodParam;
import com.apache.database.model.Page;
import com.apache.exception.BusinessException;
import com.apache.info.entity.PubMetadata;
import com.apache.info.entity.PubSortInfo;
import com.apache.info.manager.PubMetadataManager;
import com.apache.info.util.MessageUtil;
import com.apache.tools.DateUtils;
import net.sf.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.*;

public class PubMetadataManagerImpl implements PubMetadataManager {
	protected Logger log = LoggerFactory.getLogger(getClass());
	protected IDao pubMetadataDao;
	protected final String entityName = "com.apache.info.entity.PubMetadata";
	protected Map<String, PluginConnector> plugins = new HashMap<String, PluginConnector>();

	public void setPubMetadataDao(IDao pubMetadataDao) {
		this.pubMetadataDao = pubMetadataDao;
	}

	public String saveInfo(ParamsVo<PubMetadata> vo) throws BusinessException {
		PubMetadata pubMetadata = vo.getObj();
		String infoId = Validator.generate();
		//定义对象缓存KEY,如果不需要缓存对象请不要对变量赋值，如果要缓存对象建议使用infoId
		String cacheKey = "";
		//String cacheKey="pubMetadata_"+infoId;
		pubMetadata.setMetadataId(infoId);
		pubMetadata.setCreateTime(DateUtils.Now.fmt_yyyyMMdd_HHmmss());
		MethodParam param = new MethodParam("PubMetadata", cacheKey, "", entityName);
		param.setVaule(pubMetadata);
		if (Validator.isNull(pubMetadata.getIfAdd()))
			pubMetadata.setIfAdd("F");
		if (Validator.isNull(pubMetadata.getIfEdit()))
			pubMetadata.setIfEdit("F");
		if (Validator.isNull(pubMetadata.getIfList()))
			pubMetadata.setIfList("F");
		if (Validator.isNull(pubMetadata.getIfSearch()))
			pubMetadata.setIfSearch("F");
		if (Validator.isNull(pubMetadata.getReserved2()))
			pubMetadata.setReserved2("T");
		if (pubMetadataDao.insert(param)) {
			ParamsVo pvo = new ParamsVo();
			pvo.setParams("sortId", pubMetadata.getSortId());
			pvo.setParams("metadata", pubMetadata);
			if (!"F".equalsIgnoreCase(pubMetadata.getReserved2())) {
				cacheInfo(pubMetadata.getSortId(), pubMetadata, "add", null);
			}
			//			if (!Validator.isEmpty(plugins.get("updateTable"))) {//添加表字段
			//				try {
			//					if (!"F".equalsIgnoreCase(pubMetadata.getReserved2())) {
			//						plugins.get("updateTable").execute(pvo);
			//					}
			//				} catch (Exception e) {
			//					throw new BusinessException("动态修改数据[" + pubMetadata.getDataShortName() + "]字段出错", e);
			//				}
			//			}
			return infoId;
		}
		return "";
	}

	public boolean editInfo(ParamsVo<PubMetadata> vo) throws BusinessException {
		PubMetadata pubMetadata = vo.getObj();
		if (Validator.isNotNull(pubMetadata.getMetadataId())) {
			String cacheKey = "";
			//String cacheKey="pubMetadata_"+pubMetadata.getMetadataId();
			MethodParam param = new MethodParam("ById", cacheKey, "", entityName);
			param.setInfoId(pubMetadata.getMetadataId());
			PubMetadata mp = (PubMetadata) pubMetadataDao.selectById(param);
			param = new MethodParam("PubMetadata", cacheKey, "", entityName);
			pubMetadata.setCreateTime(DateUtils.Now.fmt_yyyyMMdd_HHmmss());//因无modify_time字段，则修改时同步更新创建时间
			param.setVaule(pubMetadata);
			boolean mark = pubMetadataDao.edit(param);
			if (mark) {
				if (!"F".equalsIgnoreCase(pubMetadata.getReserved2())) {
					cacheInfo(pubMetadata.getSortId(), pubMetadata, "edit", mp);
				}
				//				if (!mp.getDataLength().equals(pubMetadata.getDataLength())
				//						|| !mp.getDataShortName().equalsIgnoreCase(pubMetadata.getDataShortName())) {
				//					ParamsVo pvo = new ParamsVo();
				//					pvo.setParams("sortId", pubMetadata.getSortId());
				//					pvo.setParams("metadata", pubMetadata);
				//					pvo.setParams("old", mp);
				//					pvo.setMethodKey("modify");
				//					if (!Validator.isEmpty(plugins.get("updateTable"))) {//修改表字段
				//						try {
				//							if (!"F".equalsIgnoreCase(mp.getReserved2())) {
				//								plugins.get("updateTable").execute(pvo);
				//							}
				//						} catch (Exception e) {
				//							throw new BusinessException("动态修改数据[" + pubMetadata.getDataShortName() + "]字段出错", e);
				//						}
				//					}
				//				}
			}
			return mark;
		}
		return false;
	}

	public boolean deleteInfo(ParamsVo<PubMetadata> vo) throws BusinessException {
		String infoId = vo.getInfoId();
		if (Validator.isNull(infoId)) {
			return false;
		}
		String cacheKey = "";
		//String cacheKey="pubMetadata_"+infoId;
		//	String mark = Validator.getDefaultStr(String.valueOf(vo.getParams("isDelete")), "true");
		MethodParam param = new MethodParam("ById", cacheKey, "", entityName);
		param.setInfoId(infoId);
		PubMetadata mp = (PubMetadata) pubMetadataDao.selectById(param);
		if ("1".equals(mp.getDataRestrict())) {
			return false;
		}
		param.setInfoId("");
		param.setParams("metadataId", infoId);
		param.setDelete(true);
		boolean mark = pubMetadataDao.delete(param);
		if (mark) {
			if (!"F".equalsIgnoreCase(mp.getReserved2())) {
				cacheInfo(mp.getSortId(), mp, "del", null);
			}
		}
		return mark;
	}

	private void cacheInfo(String sortId, PubMetadata pubMetadata, String type, PubMetadata old) {
		if (Validator.isNull(pubMetadata.getDataAttr()) || Validator.isNull(pubMetadata.getDataShortName()))
			return;
		MethodParam param = new MethodParam("ById", "", "", PubSortInfo.class.getName());
		param.setInfoId(sortId);
		PubSortInfo info = (PubSortInfo) pubMetadataDao.selectById(param);
		String key = MessageUtil.getTableCacheKey(info.getSortCode(), info.getSysName(), "_tableAttr");
		String key2 = MessageUtil.getTableCacheKey(info.getSortCode(), info.getSysName(), "_tableMaps");
		String content = String.valueOf(getCache().getCacheObjectByKey(key));
		Map<String, String> cloumn = (Map) getCache().getCacheObjectByKey(key2);
		String str[];
		if (Validator.isNull(content)) {
			return;
		} else {
			str = content.split(";");
		}
		if (old != null) {
			cloumn.remove(old.getDataAttr());
		} else {
			cloumn.remove(pubMetadata.getDataAttr());
		}
		if ("edit".equals(type)) {
			log.info("edit.str[2] -1===" + str[2] + ";old=" + old.getDataShortName());
			str[2] = str[2].replace(old.getDataShortName(), "");
			str[2] = str[2].replace(",,", ",");
			log.info("edit.str[2] -2===" + str[2]);
		}
		if ("1".equals(pubMetadata.getDataRestrict())) {//主键
			str[2] = pubMetadata.getDataShortName();
		} else if ("4".equals(pubMetadata.getDataRestrict())) {//联合主键
			if ("add".equals(type)) {
				str[2] += "," + pubMetadata.getDataShortName();
			} else if ("edit".equals(type)) {
				String strId[] = str[2].split(",");
				Set<String> set = new HashSet<String>();
				//遍历数组并存入集合,如果元素已存在则不会重复存入
				for (int i = 0; i < strId.length; i++) {
					set.add(strId[i]);
				}
				set.add(pubMetadata.getDataShortName());
				//返回Set集合的数组形式
				//strId = (String[]) set.toArray();
				str[2] = strArrayToStr(set.toArray(), ",", null);
			}
			log.info ("edit.str[2]===" + str[2]);
		}
		if (!"del".equals(type)) {
			cloumn.put(pubMetadata.getDataAttr(), pubMetadata.getDataType());
		}
		if (str[2].startsWith(",")) {
			str[2] = str[2].substring(1);
		}
		StringBuilder sb = new StringBuilder();
		for (String datar : cloumn.keySet()) {
			sb.append("," + datar);
		}
		if (sb.length() > 1) {
			sb.deleteCharAt(0);
		}
		str[1] = sb.toString();
		//		if ("add".equals(type)) {
		//			str[1] = str[1] + "," + pubMetadata.getDataAttr();
		//		} else if ("edit".equals(type)) {
		//			if (str[1].indexOf(old.getDataAttr()) == -1) {
		//				str[1] = str[1] + "," + pubMetadata.getDataAttr();
		//			} else {
		//				str[1] = str[1].replace(old.getDataAttr(), pubMetadata.getDataAttr());
		//			}
		//		} else {
		//			str[1] = str[1].replace(pubMetadata.getDataAttr(), "");
		//			str[1] = str[1].replace(",,", ",");
		//		}
		if (cloumn.isEmpty() && "del".equals(type)) {
			getCache().removeCacheObject(key);
			getCache().removeCacheObject(key2);
		} else {
			String cacheContent = str[0] + ";" + str[1] + ";" + str[2] + ";" + str[3];
			getCache().createCacheObject(key, cacheContent);
			getCache().createCacheObject(key2, cloumn);
		}
	}

	private String strArrayToStr(Object[] ary, String split, String with) {
		if (null == ary) {
			return null;
		}
		if (null == split) {
			split = "";
		}
		if (with == null)
			with = "";

		StringBuffer str = null;
		for (int i = 0; i < ary.length; i++) {
			if (!Validator.isEmpty(ary[i])) {
				String temp = with + ary[i] + with;
				if (null == str) {
					str = new StringBuffer(temp);
				} else {
					str.append(split).append(temp);
				}
			}
		}
		return str == null ? null : str.toString();
	}

	public Object getInfoById(ParamsVo<PubMetadata> vo) {
		String infoId = vo.getInfoId();
		String cacheKey = "";
		//String cacheKey="pubMetadata_"+infoId;
		if (Validator.isNull(infoId)) {
			return null;
		}
		MethodParam param = new MethodParam("ById", cacheKey, "", entityName);
		param.setInfoId(infoId);
		return pubMetadataDao.selectById(param);
	}

	public Object execute(ParamsVo<PubMetadata> vo) {
		String key = vo.getKey();
		if ("ForeignKey".equals(key)) {
			return getForeignKeyS(vo);
		} else if ("initCache".equalsIgnoreCase(key)) {
			pubMetadataDao.initSystemCache();
		} else if ("updateTable".equalsIgnoreCase(key)) {
			PubMetadata pubMetadata = vo.getObj();
			if (!Validator.isEmpty(plugins.get("updateTable"))) {//添加表字段
				try {
					if (!"F".equalsIgnoreCase(pubMetadata.getReserved2())) {
						return plugins.get("updateTable").execute(vo);
					}
				} catch (Exception e) {
					throw new BusinessException("动态修改数据[" + pubMetadata.getDataShortName() + "]字段出错", e);
				}
			}
		} else if ("initCacheSysName".equalsIgnoreCase(key)) {
			String sysName = String.valueOf(vo.getParams("sysName"));
			if (Validator.isNull(sysName)) {
				pubMetadataDao.initSystemCache();
			} else {
				initCacheForSysName(sysName);
			}
		}
		return null;

	}

	/**
	 * 按系统初始化表缓存
	 * @param sysName
	 */
	private void initCacheForSysName(String sysName) {
		MethodParam param = new MethodParam("ByMetadataSysName", "", "", entityName);
		param.setParams("sysName", sysName);
		param.setResultCache(false);
		List<Map<String, String>> list = pubMetadataDao.select(param);
		if (Validator.isEmpty(list) || list.isEmpty())
			return;
		Map<String, Map<String,String>> cloumn = new HashMap<String, Map<String,String>>();
		Map<String, Map<String,String>> data = new HashMap<String, Map<String,String>>();
		for(Map<String, String> map : list){
			if ("F".equalsIgnoreCase(map.get("06")))
				continue;
			Map<String,String> cmap = data.get(map.get("09"));
			if(null == cmap){
				cmap = new HashMap<String,String>();
			}
			Map<String,String> clmMap = cloumn.get(map.get("09"));
			if(null == clmMap){
				clmMap = new HashMap<String,String>();
			}
			clmMap.put(map.get("05"), map.get("07"));
			if ("1".equals(map.get("03"))) {
				cmap.put("primaryKey",map.get("04"));
			} else if ("4".equals(map.get("03"))) {//联合主键
				cmap.put("primaryKeys",Validator.getDefaultStr(cmap.get("primaryKeys"),"")+"," + map.get("04"));
			}
			cmap.put("attrs",Validator.getDefaultStr(cmap.get("attrs"),"")+"," + map.get("05"));
			cmap.put("sortCode", map.get("08"));
			data.put(map.get("09"),cmap);
			cloumn.put(map.get("09"),clmMap);
		}
		for(String key : data.keySet()){
			Map<String,String> cmap = data.get(key);
			Map<String,String> clmMap = cloumn.get(key);
			String key1 = MessageUtil.getTableCacheKey(cmap.get("sortCode"), sysName, "_tableAttr");
			String key2 = MessageUtil.getTableCacheKey(cmap.get("sortCode"), sysName, "_tableMaps");
			String primaryKeys = cmap.get("primaryKeys");
			if (Validator.isNotNull(primaryKeys)) {
				primaryKeys = primaryKeys.substring(1);
			}
			String primaryKey = Validator.getDefaultStr(cmap.get("primaryKey"), primaryKeys);
			String cacheContent = "PubMetadata;" + cmap.get("attrs").substring(1).toString() + ";" + primaryKey + ";" + key;
			getCache().createCacheObject(key1, cacheContent);
			getCache().createCacheObject(key2, clmMap);
			log.info("add cache->["+key1+"] "+cacheContent);
			log.info("add cache->["+key2+"] "+clmMap);
		}
	}


	/**
	 * 按系统初始化表缓存
	 * @param sysName
	 */
	private void initCacheForSysName_old(String sysName) {
		MethodParam param = new MethodParam("ByMetadataSysName", "", "", entityName);
		param.setParams("sysName", sysName);
		param.setResultCache(false);
		List<Map<String, String>> list = pubMetadataDao.select(param);
		if (Validator.isEmpty(list) || list.isEmpty())
			return;
		String markTab = "";
		Map<String, String> cloumn = null;
		Map<String,JSONObject> tableMap = new HashMap<>();
		StringBuilder attrs = new StringBuilder("");
		String primaryKey = "";
		String primaryKeys = "";
		JSONObject jsonObject = new JSONObject();
		for (Map<String, String> map : list) {
			if (Validator.isNull(markTab) || !markTab.equals(map.get("09"))) {
				if (!markTab.equals(map.get("09"))) {//写缓存
					System.out.println(map.get("09"));
					String key = MessageUtil.getTableCacheKey(map.get("08"), sysName, "_tableAttr");
					String key2 = MessageUtil.getTableCacheKey(map.get("08"), sysName, "_tableMaps");
					if (attrs.length() > 0) {
						if (Validator.isNotNull(primaryKeys)) {
							primaryKeys = primaryKeys.substring(1);
						}
						primaryKey = Validator.getDefaultStr(primaryKey, primaryKeys);
						String cacheContent = "PubMetadata;" + attrs.substring(1).toString() + ";" + primaryKey + ";"
								+ map.get("09");
						getCache().createCacheObject(key, cacheContent);
						getCache().createCacheObject(key2, cloumn);
						log.info("add cache->["+key+"] "+cacheContent);
						log.info("add cache->["+key2+"] "+cloumn);
					}
				}
				markTab = map.get("09");
				attrs = new StringBuilder();
				cloumn = new HashMap<String, String>();
				primaryKey = "";
				primaryKeys = "";
			}
			if ("F".equalsIgnoreCase(map.get("06")))
				continue;
			attrs.append("," + map.get("05"));
			cloumn.put(map.get("05"), map.get("07"));
			if ("1".equals(map.get("03"))) {
				primaryKey = map.get("04");
			} else if ("4".equals(map.get("03"))) {//联合主键
				primaryKeys += "," + map.get("04");
			}
		}
		log.info("系统["+sysName+"]下所有[数据表信息]到缓存中...end !");
	}

	private List getForeignKeyS(ParamsVo<PubMetadata> vo) {
		MethodParam param = setMethodParams(vo, 2);
		param.setKey("ByForeignKey");
		return pubMetadataDao.select(param);
	}

	public Page getPageInfo(ParamsVo<PubMetadata> vo) {
		MethodParam param = setMethodParams(vo, 2);
		int pageSize = Integer.valueOf(Validator.getDefaultStr(String.valueOf(vo.getParams("pageSize")), "10"));
		int pageIndex = Integer.valueOf(Validator.getDefaultStr(String.valueOf(vo.getParams("pageIndex")), "1"));
		param.setPageIndex(pageIndex);
		param.setPageSize(pageSize);
		Page page = pubMetadataDao.pageSelect(param);
		return page;
	}

	public List<PubMetadata> getList(ParamsVo<PubMetadata> vo) {
		MethodParam param = setMethodParams(vo, 2);
		return pubMetadataDao.select(param);
	}

	public long countInfo(ParamsVo<PubMetadata> vo) {
		MethodParam param = setMethodParams(vo, 1);
		return pubMetadataDao.count(param);
	}

	private MethodParam setMethodParams(ParamsVo<PubMetadata> vo, int type) {
		String methodKey = Validator.getDefaultStr(vo.getMethodKey(), "ByProperty");
		MethodParam param = new MethodParam(methodKey, "", "", entityName);
		PubMetadata pubMetadata = vo.getObj();
		if (Validator.isNotNull(pubMetadata.getSortId())) {
			param.setParams("sortId", pubMetadata.getSortId());
		}
		if (Validator.isNotNull(pubMetadata.getDataFullName())) {
			param.setParams("dataFullName", pubMetadata.getDataFullName());
		}
		if (Validator.isNotNull(pubMetadata.getDataShortName())) {
			param.setParams("dataShortName", pubMetadata.getDataShortName());
		}
		if (Validator.isNotNull(pubMetadata.getDataRestrict())) {
			param.setParams("dataRestrict", pubMetadata.getDataRestrict());
		}
		if (Validator.isNotNull(pubMetadata.getForeignKeyName())) {
			param.setParams("foreignKeyName", pubMetadata.getForeignKeyName());
		}
		if (Validator.isNotNull(pubMetadata.getReserved1())) {
			param.setParams("reserved1", pubMetadata.getReserved1());
		}
		if (Validator.isNotNull(pubMetadata.getReserved2())) {
			param.setParams("reserved2", pubMetadata.getReserved2());
		}
		if (Validator.isNotNull(pubMetadata.getReserved3())) {
			param.setParams("reserved3", pubMetadata.getReserved3());
		}
		return param;
	}

	public void setPlugins(Map<String, PluginConnector> plugins) {
		this.plugins = plugins;
	}

	private CacheManager getCache() {
		return LoadCacheFactory.getInstance().getCacheManager("");
	}
}
